/**
 * 
 */
package klk.shop.objects;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import klk.shop.utilities.HTMLUtilities;
import klk.shop.utilities.MysqlUtilities;

/**
 * @author kev
 * Die Klasse stellt den Privatkunden dar,
 */
public class Customer extends KLKObject {
	
	
	protected int customerId; // wenn -1,dann noch nicht in der datenbank/nicht abgeglichen?
	protected String email;
	protected int title;
	protected String name;
	protected String surname;
	protected Date birthDate;
	protected Date registrationDate;
	protected String language;
	protected boolean isVerified;
	protected ArrayList<Address> addressList; // 0=default-contact, 1=default-shipping
	protected ArrayList<BankAccount> bankAccountList;
	protected ArrayList<CreditCard> creditCardList;
	
	
	public int getCustomerId() {
		return customerId;
	}
	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}
	
	public String getEmail() {
		return email;
	}
	public boolean setEmail(String email) {
		this.email = email;
		return (email!=null && !email.equals(""));
	}
	
	public int getTitle() {
		return title;
	}
	public boolean setTitle(int title) {
		this.title = title;
		return (title==0 || title==1);
	}
	public boolean setTitle(String titleString) {
		try {
			this.title = Integer.parseInt(titleString);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	public String getName() {
		return name;
	}
	public boolean setName(String name) {
		this.name = name;
		return (name!=null && !name.equals(""));
	}
	
	public String getSurname() {
		return surname;
	}
	public boolean setSurname(String surname) {
		this.surname = surname;
		return (surname!=null && !surname.equals(""));
	}
	
	public Date getBirthDate() {
		return birthDate;
	}
	public boolean setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
		return (birthDate!=null && !birthDate.equals(new Date()));
	}
	@SuppressWarnings("deprecation")
	public boolean setBirthDate(String day, String month, String year) {
		try {
			this.birthDate = new Date();
			this.birthDate.setDate(Integer.parseInt(day));
			this.birthDate.setMonth(Integer.parseInt(month)-1);
			this.birthDate.setYear(Integer.parseInt(year)-1900);
			return true;
		} catch (Exception e) {
			return false;
		}	
	}
	public Date getRegistrationDate() {
		return registrationDate;
	}
	public boolean setRegistrationDate(Date registrationDate) {
		this.registrationDate = registrationDate;
		return (registrationDate!=null && !registrationDate.equals(new Date()));
	}
	
	public String getLanguage() {
		return language;
	}
	public boolean setLanguage(String language) {
		this.language = language;
		return (language!=null && !language.equals(""));
	}
	
	public boolean isVerified() {
		return isVerified;
	}
	public void setVerified(boolean isVerified) {
		this.isVerified = isVerified;
	}
	
	public ArrayList<Address> getAddressList() {
		return addressList;
	}
	public void setAddressList(ArrayList<Address> addressList) {
		this.addressList = addressList;
	}
	public Address getDefaultContactAddress() {
		return addressList.get(0);
	}
	public void setDefaultContactAddress(Address address) {
		addressList.set(0, address);
	}
	public Address getDefaultShippingAddress() {
		if (addressList.get(1)==null)
			return addressList.get(0);
		return addressList.get(1);
	}
	public void setDefaultShippingAddress(Address address) {
		addressList.set(1, address);
	}
	public void addAddress(Address address) {
		if (addressList.get(0)==null)
			addressList.set(0, address);
		else if (addressList.get(1)==null)
			addressList.set(1, address);
		else
			addressList.add(address);
	}
	public void removeAddress(int index) {
		addressList.remove(index);
	}
	public void removeAddress(Address address) {
		addressList.remove(address);
	}
		
	public ArrayList<BankAccount> getBankAccountList() {
		return bankAccountList;
	}
	public void setBankAccountList(ArrayList<BankAccount> bankAccountList) {
		this.bankAccountList = bankAccountList;
	}
	public void addBankAccount(BankAccount bankAccount) {
		if (bankAccountList.get(0)==null)
			bankAccountList.set(0, bankAccount);
		else
			bankAccountList.add(bankAccount);
	}
	public void removeBankAccount(int index) {
		bankAccountList.remove(index);
	}
	public void removeBankAccount(BankAccount bankAccount) {
		bankAccountList.remove(bankAccount);
	}
	
	public ArrayList<CreditCard> getCreditCardList() {
		return creditCardList;
	}
	protected void setCreditCardList(ArrayList<CreditCard> creditCardList) {
		this.creditCardList = creditCardList;
	}
	public void addCreditCard(CreditCard creditCard) {
		if (creditCardList.get(0)==null)
			creditCardList.set(0, creditCard);
		else
			creditCardList.add(creditCard);
	}
	public void removeCreditCard(int index) {
		creditCardList.remove(index);
	}
	public void removeCreditCard(CreditCard creditCard) {
		creditCardList.remove(creditCard);
	}
	
	
	public Customer(int customerId, String email, int title, String name,
			String surname, Date birthDate, Date registrationDate, String language, 
			boolean isVerified, ArrayList<Address> addressList,
			ArrayList<BankAccount> bankAccountList,
			ArrayList<CreditCard> creditCardList) {
		super();
		this.customerId = customerId;
		this.email = email;
		this.title = title;
		this.name = name;
		this.surname = surname;
		this.birthDate = birthDate;
		this.registrationDate = registrationDate;
		this.language = language;
		this.isVerified = isVerified;
		this.addressList = addressList;
		this.bankAccountList = bankAccountList;
		this.creditCardList = creditCardList;
		
		while (addressList.size()<2)
			addressList.add(null); // [0]=>contact // [1]=>shipping
		while (bankAccountList.size()<1)
			bankAccountList.add(null);
		while (creditCardList.size()<1)
			creditCardList.add(null);
		
	}
	public Customer() {
		this(	
			-1, "", 0, "", "", new Date(), new Date(), "de", false, 
			new ArrayList<Address>(),
			new ArrayList<BankAccount>(),
			new ArrayList<CreditCard>()
		);
	}

	
	@Override
	public String toString() {
		char nl = '\n';
		StringBuilder sb = new StringBuilder("Customer:" + nl);
		sb.append("customerId:         " + customerId + nl);
		sb.append("email:              " + email + nl);
		sb.append("title:              " + title + nl);
		sb.append("name:               " + name + nl);
		sb.append("surname:            " + surname + nl);
		sb.append("birthDate:          " + birthDate + nl);
		sb.append("registrationDate:   " + registrationDate + nl);
		sb.append("language:           " + language + nl);
		sb.append("isVerified:         " + isVerified + nl);
		int iMax = addressList.size();
		sb.append("addressList:" + nl);
		for (int i = 0; i < iMax; i++) {
			sb.append("addressList["+i+"]: " + addressList.get(i) + nl);
		}
		iMax = bankAccountList.size();
		sb.append("bankAccountList:" + nl);
		for (int i = 0; i < iMax; i++) {
			sb.append("bankAccountList["+i+"]: " + bankAccountList.get(i) + nl);
		}
		iMax = creditCardList.size();
		sb.append("creditCardList:" + nl);
		for (int i = 0; i < iMax; i++) {
			sb.append("creditCardList["+i+"]: " + creditCardList.get(i) + nl);
		}
		return sb.toString();
	}
	
	@Override
	public String toHtml() {
		StringBuilder sb = new StringBuilder();		
		sb.append( "<table>" );
		sb.append( nl );
		sb.append( HTMLUtilities.TableRow("Customer:") );
		sb.append( HTMLUtilities.TableRow("customerId:", customerId) );
		sb.append( HTMLUtilities.TableRow("email:", email) );
		sb.append( HTMLUtilities.TableRow("title:", title) );
		sb.append( HTMLUtilities.TableRow("name:", name) );
		sb.append( HTMLUtilities.TableRow("surname:", surname) );
		sb.append( HTMLUtilities.TableRow("birthDate:", birthDate) );
		sb.append( HTMLUtilities.TableRow("registrationDate:", registrationDate) );
		sb.append( HTMLUtilities.TableRow("isVerified:", isVerified) );

		sb.append( nl );
		int iMax = addressList.size();
		sb.append("addressList:" + nl);
		for (int i = 0; i < iMax; i++) {
			if (addressList.get(i)!=null) {
				sb.append( HTMLUtilities.TableRow("addressList["+i+"]:", addressList.get(i).toHtml()) );
				sb.append(nl);
			}
		}
		iMax = bankAccountList.size();
		sb.append("bankAccountList:" + nl);
		for (int i = 0; i < iMax; i++) {
			if (bankAccountList.get(i)!=null) {
				sb.append( HTMLUtilities.TableRow("bankAccountList["+i+"]:", bankAccountList.get(i).toHtml()) );
				sb.append(nl);				
			}

		}
		iMax = creditCardList.size();
		sb.append("creditCardList:" + nl);
		for (int i = 0; i < iMax; i++) {
			if (creditCardList.get(i)!=null) {
				sb.append( HTMLUtilities.TableRow("creditCardList["+i+"]:", creditCardList.get(i).toHtml()) );
				sb.append(nl);
			}
		}
		sb.append( "</table>" );
		
		return sb.toString();
	}
	
	
	

	public static Customer getCustomerFromDatabase(String localeString, int customerId) {
		Customer customer = new Customer();
		
		DataSource ds;	
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
				
		try	{
			
			InitialContext ic=new InitialContext();
			ds=(DataSource)ic.lookup("java:comp/env/jdbc/klkshop");
			conn=ds.getConnection();
			stmt = conn.createStatement();
			
			rs = stmt.executeQuery(
				"SELECT " +
					"email_address, " +
					"title, " +
					"name, " +
					"surname, " +
					"birthdate, " +
					"registration_date, " +
					"language, " +
					"statuscode " + 
				"FROM " +
					"customers " +
				"WHERE id="+customerId+"; "
			);
			
			rs.next();
			
			customer.setCustomerId(customerId);
			customer.setEmail(rs.getString("email_address"));
			customer.setTitle(rs.getInt("title"));
			customer.setName(rs.getString("name"));
			customer.setSurname(rs.getString("surname"));
			customer.setBirthDate(rs.getDate("birthdate"));
			customer.setRegistrationDate(rs.getDate("registration_date"));
			customer.setLanguage(rs.getString("language"));
			
			int statusCode = rs.getInt("statuscode");
			if (  ( statusCode & (1<<0) )==(1<<0)  ) {					// 1
				customer = BusinessCustomer.getBusinessCustomerFromDatabase(customer);
			}
			customer.setVerified(  ( statusCode & (1<<1) )==(1<<1)  );	// 2
			
			customer.setAddressList(
				Address.getCustomersAddressListFromDatabase(
					localeString, customer.getCustomerId() 
				)
			);
			customer.setBankAccountList(
				BankAccount.getCustomersBankAccountListFromDatabase(
					customer.getCustomerId()
				)
			);
			customer.setCreditCardList(
				CreditCard.getCustomersCreditCardListFromDatabase(
					customer.getCustomerId()
				)
			);
			
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rs != null) try { rs.close(); } catch(Exception e) {}
			if (stmt != null) try { stmt.close(); } catch(Exception e) {}
			if (conn != null) try { conn.close(); } catch(Exception e) {}
	    }
		
		return customer;	
	}
	
	public static Customer getCustomerFromDatabase(String localeString, String customerEmail) {
		Customer customer = new Customer();
		
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
				
		try	{
			
			conn = MysqlUtilities.getConnection();
			stmt = conn.createStatement();
			
			rs = stmt.executeQuery(
				"SELECT " +
					"id, " +
					"title, " +
					"name, " +
					"surname, " +
					"birthdate, " +
					"registration_date, " +
					"language, " +
					"statuscode " + 
				"FROM " +
					"customers " +
				"WHERE email_address='"+customerEmail+"'; "
			);
			
			rs.next();
			
			customer.setCustomerId(rs.getInt("id"));
			customer.setEmail(customerEmail);
			customer.setTitle(rs.getInt("title"));
			customer.setName(rs.getString("name"));
			customer.setSurname(rs.getString("surname"));
			customer.setBirthDate(rs.getDate("birthdate"));
			customer.setRegistrationDate(rs.getDate("registration_date"));
			customer.setLanguage(rs.getString("language"));
			
			int statusCode = rs.getInt("statuscode");
			if (  ( statusCode & (1<<0) )==(1<<0)  ) {					// 1
				customer = BusinessCustomer.getBusinessCustomerFromDatabase(customer);
			}
			customer.setVerified(  ( statusCode & (1<<1) )==(1<<1)  );	// 2

			customer.setAddressList(
				Address.getCustomersAddressListFromDatabase(
					localeString, customer.getCustomerId() 
				)
			);
			customer.setBankAccountList(
				BankAccount.getCustomersBankAccountListFromDatabase(
					customer.getCustomerId()
				)
			);
			customer.setCreditCardList(
				CreditCard.getCustomersCreditCardListFromDatabase(
					customer.getCustomerId()
				)
			);
			
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rs != null) try { rs.close(); } catch(Exception e) {}
			if (stmt != null) try { stmt.close(); } catch(Exception e) {}
			if (conn != null) try { conn.close(); } catch(Exception e) {}
	    }
		
		return customer;	
	}

	public static int SetCustomerIntoDatabase(String localeString, Customer customer) {
		
		int rowsAffected = 0, statusCode = 0;
		statusCode += (customer instanceof BusinessCustomer)?	1<<0 : 0;
		statusCode += (customer.isVerified())?					1<<1 : 0;

		String birthDateString = MysqlUtilities.toMySqlDateString(customer.getBirthDate());
		String registrationDateString = MysqlUtilities.toMySqlDateString(customer.getRegistrationDate());
		
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		if (customer.getCustomerId()==-1) {
			try	{
			
				conn= MysqlUtilities.getConnection();
				stmt = conn.createStatement();
				
				String insertString = 
						"INSERT INTO `customers` (" +
							"email_address, title, name, surname, birthdate, registration_date, language, statuscode" +
						") VALUES (" +
							"'" + 	customer.getEmail() 	+ "'" 	+ ", " + 
									customer.getTitle() 			+ ", " +  
							"'" + 	customer.getName() 		+ "'" 	+ ", " + 
							"'" + 	customer.getSurname() 	+ "'" 	+ ", " + 
							"'" + 	birthDateString 		+ "'" 	+ ", " + 
							"'" + 	registrationDateString 	+ "'" 	+ ", " + 
							"'" + 	customer.getLanguage() 	+ "'" 	+ ", " + 
									statusCode + 
							");";
				System.out.println(insertString);
				rowsAffected = conn.createStatement().executeUpdate( insertString ); 
				
				stmt = conn.createStatement();
				rs = stmt.executeQuery(
					"SELECT LAST_INSERT_ID();"
				);
				rs.next();
				customer.setCustomerId(rs.getInt("LAST_INSERT_ID()"));
				
				ArrayList<Address> addressList = customer.getAddressList();
				int iMax = addressList.size();
				for (int i = 0; i < iMax; i++) {
					if (addressList.get(i)!=null)
						Address.SetAddressIntoDatabase(addressList.get(i), customer, localeString);
				}
				ArrayList<BankAccount> bankAccountList = customer.getBankAccountList();
				iMax = bankAccountList.size();
				for (int i = 0; i < iMax; i++) {
					if (bankAccountList.get(i)!=null)
						BankAccount.SetBankAccountIntoDatabase(bankAccountList.get(i), customer);
				}
				ArrayList<CreditCard> creditCardList = customer.getCreditCardList();
				iMax = creditCardList.size();
				for (int i = 0; i < iMax; i++) {
					if (creditCardList.get(i)!=null)
						CreditCard.SetCreditCardIntoDatabase(creditCardList.get(i), customer);
				}
				
				
				
			} catch (Exception e) {
				e.printStackTrace();
				
			} finally {
				if (rs != null) try { rs.close(); } catch(Exception e) {}
				if (stmt != null) try { stmt.close(); } catch(Exception e) {}
				if (conn != null) try { conn.close(); } catch(Exception e) {}
		    }
		
		} else {
			
			try	{

				conn= MysqlUtilities.getConnection();
				stmt = conn.createStatement();
				
				String updateString = 
						"UPDATE `customers` " +
							"SET email_address='" + customer.getEmail() + "', " +
							"statuscode=" + statusCode + ", " +
							"title=" + customer.getTitle() + ", " +
							"name='" + customer.getName() + "', " +
							"surname='" + customer.getSurname() + "', " +
							"birthdate='" + birthDateString + "', " + 
							"statuscode=" + statusCode + ", " +
							"language='" + customer.getLanguage() + "' " +
						"WHERE " +
							"id=" + customer.getCustomerId()+ 
						";";
				System.out.println(updateString);
				rowsAffected = conn.createStatement().executeUpdate( updateString ); 
				
			} catch (Exception e) {
				e.printStackTrace();
				
			} finally {
				if (rs != null) try { rs.close(); } catch(Exception e) {}
				if (stmt != null) try { stmt.close(); } catch(Exception e) {}
				if (conn != null) try { conn.close(); } catch(Exception e) {}
		    }
		}
		
		
		
		return rowsAffected;	
	}
	
	public static boolean DeleteUnverifiedCustomerFromDatabase(int customerId) {
		boolean success = true;

		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;		
		try	{
			conn= MysqlUtilities.getConnection();
			stmt = conn.createStatement();

			String deleteString = 
					"DELETE FROM `customer` " +
					"WHERE " +
						"customer_id=" + customerId + " AND " + 
						"(statuscode & 2)=0" + // isVerified darf nicht gesetzt sein!
					";";
			if ( conn.createStatement().executeUpdate( deleteString ) < 1 )
				success = false;
			
		} catch (Exception e) {
			e.printStackTrace();
			success = false;
			
		} finally {
			if (  rs != null) try {   rs.close(); } catch(Exception e) {}
			if (stmt != null) try { stmt.close(); } catch(Exception e) {}
			if (conn != null) try { conn.close(); } catch(Exception e) {}
	    }
		
		return success;	
	}

}
